package com.apes.scm.masterdata.finance.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Filter;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.finance.model.CrossDefiIC;
import com.apes.scm.masterdata.finance.model.CrossDept;
import com.apes.scm.masterdata.finance.model.CrossIC;
import com.apes.scm.masterdata.finance.model.CrossICServe;
import com.apes.scm.masterdata.finance.repository.CrossDefICRepository;
import com.apes.scm.masterdata.finance.repository.CrossDeptRepository;
import com.apes.scm.masterdata.finance.repository.CrossICRepository;
import com.apes.scm.masterdata.finance.repository.CrossICServeRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import javax.swing.text.html.Option;
import java.util.*;
import java.util.stream.Collectors;


/**
 * Creator: zouyc
 * CreateDate: 2020-06-10 9:14
 * Description:
 **/
@Service("crossICService")
public class CrossICService extends DomainService {
    @Autowired
    CrossICRepository crossICRepository;
    @Autowired
    CrossDefICRepository crossDefICRepository;
    @Autowired
    CrossICServeRepository crossICServeRepository;
    @Autowired
    CrossDeptRepository crossDeptRepository;
    @Autowired
    ProductRepository productRepository;
    @Autowired
    DeptRepository deptRepository;


    private void check(CrossIC crossIC){
//        if(crossIC.getProduct() != null && crossIC.getClassify() != null){
//            throw new RuntimeException("商品和品类不能同时存在");
//        }
    }

    public CrossIC create(SimpleRequest req){
        CrossIC crossIC = req.getO(CrossIC.class);
        return save(crossIC);
    }

    private CrossIC save(CrossIC crossIC){
        check(crossIC); //对数据进行校验
        crossIC = crossICRepository.saveAndFlush(crossIC);
        return crossIC;
    }

    public CrossIC update(SimpleRequest req){
        CrossIC crossIC = req.getO(CrossIC.class);
        return save(crossIC);
    }

    /**
     * 查找所有合作方
     * @param req
     * @return
     */
    public JSONArray findAllCross(SimpleRequest req){
        JSONObject jo = req.getJO();
        Dept dept = deptRepository.findOne(jo.getString("dept"));
        List<CrossDefiIC> all = crossDefICRepository.findAllByCompanyIn(dept.getCompany().getId());
        JSONArray result = new JSONArray();
        all.stream().filter(crossDefiIC -> {//过滤配置了不可抵扣部门的合作方
            if (crossDefiIC!=null){
                List<CrossDept> CrossDept = crossDefiIC.getCrossDepts().stream().filter(crossDept -> {
                    return crossDept.getDept().getId().equals(dept.getId());
                }).collect(Collectors.toList());
                return CrossDept.size()==0;
            }
            return true;
        }).forEach(crossDefiIC -> {
            JSONObject idAndName = new JSONObject();
            idAndName.put("id",crossDefiIC.getId());
            idAndName.put("name",crossDefiIC.getName());
            if (crossDefiIC.isValid()){
                result.add(idAndName);
            }
        });
        return result;
    }

    public String checkDpet(JSONArray filters,String dept){
        for (int i = 0; i < filters.size(); i++) {
            JSONObject filterObj = (JSONObject) filters.get(i);
            if (filterObj.getString("field").equals("dept.id")){
                dept=filterObj.getString("value");
                filters.remove(i);
            };
        }
        return dept;
    }


    /**
     * 查询所有服务并且过滤不可抵扣的合作方返回给前端
     */
    public Page<CrossICServe> findAllServiceByDept(SimpleRequest req){
        JSONObject jo = req.getJO();
        JSONArray filters = req.getJO().getJSONObject("group").getJSONArray("filters");
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        String dept = null;
        String deptId = checkDpet(filters,dept);
        List<CrossICServe> crossICServes = crossICServeRepository.findAll(JpaDsl.toCriteria(filters),sort);
        if (deptId!=null){
            List<CrossDept> crossDepts = crossDeptRepository.findAllByDept(deptRepository.findOne(deptId));
            crossICServes = crossICServes.stream().filter(crossICServe -> crossICServe.isValid()).filter(crossICServe -> {
                CrossDept orElse = crossDepts.stream().filter(crossDept -> crossDept.getCrossDefiIC().getId().equals(crossICServe.getCrossDefiIC().getId())).findFirst().orElse(null);
                return orElse == null;
            }).collect(Collectors.toList());
        }
        return pageInfo(jo,crossICServes,sort);
    }

    /**
     * 手动分页
     * @param jo
     * @param cross
     * @param sort
     * @return
     */
    public PageImpl pageInfo(JSONObject jo, List cross,Sort sort){
        int size = (Integer) jo.get("page")*(Integer) jo.get("size");
        List result = new ArrayList<>();
        for (int i = size+1; i <= size+(Integer) jo.get("size"); i++) {
            if (cross.size()>=i)result.add(cross.get(i-1));
        }
        Pageable pageable = PageRequest.of(((Integer) jo.get("page")), (Integer) jo.get("size"),sort);
        PageImpl page = new PageImpl(result, pageable, cross.size());
        return page;
    }
    /**
     * 手动分页(制单页面初始化不能分页,数据量不大一次性塞进content里)
     * @param jo
     * @param cross
     * @param sort
     * @return
     */
    public PageImpl pageInfoAllContent(JSONObject jo, List cross,Sort sort){
        Pageable pageable = PageRequest.of(((Integer) jo.get("page")), (Integer) jo.get("size"),sort);
        PageImpl page = new PageImpl(cross, pageable, cross.size());
        return page;
    }


    /**
     * 手动分页
     * @param jo
     * @param cross
     * @return
     */
    public PageImpl pageInfo(JSONObject jo, List cross){
        int size = (Integer) jo.get("page")*(Integer) jo.get("size");
        List result = new ArrayList<>();
        for (int i = size+1; i <= size+(Integer) jo.get("size"); i++) {
            if (cross.size()>=i)result.add(cross.get(i-1));
        }
        Pageable pageable = PageRequest.of(((Integer) jo.get("page")), (Integer) jo.get("size"));
        PageImpl page = new PageImpl(result, pageable, cross.size());
        return page;
    }


    /**
     * 查询所有合作方并且过滤不可抵扣的合作方返回给前端
     * @param req
     * @return
     */
    public Page<CrossDefiIC> findAllByDept(SimpleRequest req){
        JSONObject jo = req.getJO();
        JSONArray filters = req.getJO().getJSONObject("group").getJSONArray("filters");
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        String dept = null;
        String deptId = checkDpet(filters,dept);
        List<CrossDefiIC> crossDefiICS = crossDefICRepository.findAll(JpaDsl.toCriteria(filters),sort).stream().filter(crossDefiIC -> crossDefiIC.isValid()).collect(Collectors.toList());

        if (deptId!=null){
            crossDefiICS = crossDefiICS.stream().sorted(Comparator.comparing(crossDefiIC -> crossDefiIC.getId())).filter(crossDefiIC -> {
                List<CrossDept> crossDepts = crossDefiIC.getCrossDepts().stream().filter(crossDept -> crossDept.getDept().getId().equals(deptId)).collect(Collectors.toList());
                return crossDepts.size() != 0 ? false : true;
            }).collect(Collectors.toList());
        }
        return pageInfoAllContent(jo,crossDefiICS,sort);

    }

    /**
     * 验证是否配置不可抵扣门店
     * @param req
     */
    public void checkDeptAuth(SimpleRequest req){
        JSONObject jo = req.getJO();
        String crossId = jo.getString("crossId");
        String deptId = jo.getString("deptId");
        CrossDefiIC crossDefiIC = crossDefICRepository.findOne(crossId);
        List<CrossDept> crossDepts = crossDefiIC.getCrossDepts().stream().filter(crossDept -> crossDept.getDept().getId().equals(deptId)).collect(Collectors.toList());
        if (crossDepts.size()!=0)throw new RuntimeException("该门店已配置不可抵扣");
    }

    /**
     * 查找合作方的所有服务类型
     * @param req
     * @return
     */
    public JSONArray findAllCrossIc(SimpleRequest req){
        JSONObject param = req.getJO();
        CrossDefiIC crossDefiIC = crossDefICRepository.findAll(JpaDsl.toCriteriaByEq(
                "id", param.getString("id"))).stream().findFirst().orElse(null);
        return checkCross(crossDefiIC.getCrossICServes());
    }

    /**
     * 处理合作方服务类型返回数据
     * @param crossICServes
     * @return
     */
    public JSONArray checkCross(List<CrossICServe> crossICServes){
        JSONArray results = new JSONArray();
        crossICServes.stream().filter(crossICServe -> crossICServe.isValid()).forEach(crossICServe ->{
            JSONObject result = new JSONObject();
            Product product = crossICServe.getProduct();
            JSONArray products = new JSONArray();
            products.add(MapUtil.mapper(
                    "id",product.getId(),
                    "name",product.getName(),
                    "productGroup",product.getProductGroup().getId()
                    ));
            result.put("products",products);
            result.put("crossPayType",crossICServe.getCrossPayType().getDescription());
            result.put("name",crossICServe.getName());
            result.put("id",crossICServe.getId());
            result.put("crossParent",crossICServe.getCrossParent());
            results.add(result);
        });
        return results;
    }

    /**
     * 查找异业合作服务类型价格
     * @param req
     * @return
     */
    public Map findOneCrossIc(SimpleRequest req){
        JSONObject jo = req.getJO();
        JSONObject conditionModel = jo.getJSONObject("conditionModel");
        String productId = jo.getString("productId");
        Product one = productRepository.getOne(productId);
        JSONObject belongDept = conditionModel.getJSONObject("belongDept");
        conditionModel.put("saleDept",belongDept);
        JSONObject price = this.invoke("fn.service.getPrise", MapUtil.mapper(
                "conditionModel", conditionModel,
                "condition", JSONObject.toJSONString(one)));
//        CrossIC cross = crossICRepository.findByIdAndCrossId(jo.getString("serviceId"), jo.getString("crossId"));
        Map crossICPrice = this.invoke("fn.crossIC.calculateCrossIC", MapUtil.mapper(
                "productID", productId,
                "pftUnit",price.getDoubleValue("pftPriceUnit"),
                "crossID",jo.getString("serviceId"),
                "belongID",belongDept.getString("id")
        ));

        return MapUtil.mapper(
                "accountPrice",crossICPrice.get("deductionUnit"),
                "customerPrice",crossICPrice.get("crossCustomerPrice"),
                "crossPriceCost",crossICPrice.get("crossPriceCost"),
                "pftPriceUnit",price.getDoubleValue("pftPriceUnit"),
                "productGroup",one.getProductGroup().getId(),
                "uomName",JSONObject.parseObject(JSONObject.toJSONString(price.get("uom"))).getString("name"),
                "primaryPriceUnit",price.getDoubleValue("primaryPriceUnit"),
                "basePrice",price.getDoubleValue("basePrice"),
                "saleQty",price.getInteger("saleQty"),
                "floorPrice",price.getDoubleValue("floorPrice"),
                "location",JSONObject.parseObject(JSONObject.toJSONString(price.get("location"))).getString("id"),
                "priceUnit",price.getDoubleValue("priceUnit"),
                "deductionUnit",crossICPrice.get("deductionUnit")
        );
    }


    public CrossDefiIC defCreate(SimpleRequest req){
        CrossDefiIC crossDefiIC = req.getO(CrossDefiIC.class);
        checkCrossDeptRepetition(crossDefiIC);
        if(crossDefiIC.getCrossICServes().size() == 0) throw new RuntimeException("服务明细行不能为空");
        crossDefiIC = crossDefICRepository.saveAndFlush(crossDefiIC);
        updateCrossICByDef(crossDefiIC);
        return  crossDefiIC;
    }

    public CrossDefiIC defUpdate(SimpleRequest req){
        CrossDefiIC crossDefiIC = req.getO(CrossDefiIC.class);
        checkCrossDeptRepetition(crossDefiIC);
        if(crossDefiIC.getCrossICServes().size() == 0) throw new RuntimeException("服务明细行不能为空");
        try {
            crossDefiIC = crossDefICRepository.saveAndFlush(crossDefiIC);
        } catch (Exception e) {
            if (e.getMessage().contains("ORA-02292"))throw new RuntimeException("有商品明细已使用该异业服务无法删除，如不需要请在明细设置为无效！");
            e.printStackTrace();
        }
        updateCrossICByDef(crossDefiIC);
        return crossDefiIC;
    }
    public void checkCrossDeptRepetition(CrossDefiIC crossDefiIC){
        List<CrossDept> crossDepts = crossDefiIC.getCrossDepts();
        Map map = new HashMap();
        crossDepts.stream().forEach(crossDept -> {
            if (map.get(crossDept.getDept().getId())!=null) throw new RuntimeException(crossDept.getDept().getName()+"重复!");
            map.put(crossDept.getDept().getId(),crossDept.getDept().getName());
        });
    }

    public void updateCrossICByDef(CrossDefiIC crossDefiIC){
        List<CrossICServe> crossICServes = crossDefiIC.getCrossICServes();
        crossICServes.forEach(crossICServe ->{
            CrossIC crossIC= crossICRepository.findOne(crossICServe.getId()) ;
            crossIC = crossIC == null ? new CrossIC() : crossIC;
            crossIC.setCrossId(crossDefiIC.getId());
            crossIC.setCrossName(crossDefiIC.getName());
            crossIC.setCompany(crossDefiIC.getCompany());
            crossIC.setPartner(crossDefiIC.getPartner());
            crossIC.setId(crossICServe.getId());
            crossIC.setName(crossICServe.getName());
            crossIC.setProduct(crossICServe.getProduct());
            crossIC.setClassify(crossICServe.getClassify());
            crossIC.setCrossPayType(crossICServe.getCrossPayType());
            crossIC.setValid(  crossDefiIC.isValid() ? (crossICServe.isValid() ? true : false) : false  );
            save(crossIC);
        });
    }

    public Page<CrossDefiIC> findAllForDef(SimpleRequest req){
        List<Filter> condition1Array = new ArrayList();
        List<Filter> condition2Array = new ArrayList();
        JSONArray cArray = req.get("condition");
        cArray.stream().forEach(item ->{
            JSONObject itemJson  = (JSONObject)item;
            String field = itemJson.getString("field");
            String  value = itemJson.getString("value");
            String  operator = itemJson.getString("operator");

            if("rexLike".equals(field)){
                condition1Array.add(new Filter("id",value,operator,""));
                condition1Array.add(new Filter("name",value,operator,""));
                condition1Array.add(new Filter("partner.party.name",value,operator,""));
            }else if("validSel".equals(field)){
                if("valid".equals(value)){
                    condition2Array.add(new Filter("valid",true,operator,""));
                }else if("unValid".equals(value)){
                    condition2Array.add(new Filter("valid",false,operator,""));
                }
            }
        });
        Group grouR = new Group();
        grouR.setFilters(condition2Array);
        grouR.setOperator("and");
        Group groupInner = new Group();
        groupInner.setFilters(condition1Array);
        groupInner.setOperator("or");
        List<Group> list = new ArrayList<>();
        list.add(groupInner);
        if(condition1Array.size() != 0) grouR.setGroups(list);
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageable = PageRequest.of(req.get("page"), req.get("size"), sort);
        return  crossDefICRepository.findAll(grouR.build(true),pageable);
    }



    public Map regrepChild(SimpleRequest re){
        JSONObject jo = re.getJO();
        JSONObject product = jo.getJSONObject("product");
        JSONObject classify = product.getJSONObject("classify");
        JSONObject cross = jo.getJSONObject("crossID");

        if(product == null || classify == null || cross == null) return null;

        List<Filter> condition1Array = new ArrayList();
        List<Filter> condition2Array = new ArrayList();

        Group grouR = new Group();
        condition1Array.add(new Filter("crossDefiIC.id",cross.getString("id"),"EQ",""));
        grouR.setFilters(condition1Array);
        grouR.setOperator("and");
        Group groupInner = new Group();
        condition2Array.add(new Filter("product.id",product.getString("id"),"EQ",""));
        condition2Array.add(new Filter("classify.id",classify.getString("id"),"EQ",""));
        groupInner.setFilters(condition2Array);
        groupInner.setOperator("or");
        List<Group> list = new ArrayList<>();
        list.add(groupInner);
        grouR.setGroups(list);
        List<CrossICServe> crossICServes = crossICServeRepository.findAll(grouR.build(true));
        if(crossICServes.size() == 1) return MapUtil.mapped(crossICServes.stream().findFirst().get());
        return null;
    }

}
